package com.wpan.gulimall.product.service.impl;

import com.wpan.gulimall.product.service.CategoryBrandRelationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wpan.common.utils.PageUtils;
import com.wpan.common.utils.Query;

import com.wpan.gulimall.product.dao.CategoryDao;
import com.wpan.gulimall.product.entity.CategoryEntity;
import com.wpan.gulimall.product.service.CategoryService;
import org.springframework.transaction.annotation.Transactional;
import sun.rmi.runtime.Log;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 查询出所有的分类信息
     * @return
     */
    @Override
    public List<CategoryEntity> listWithTree() {
        //1.查询出所有的分类
        List<CategoryEntity> entities = baseMapper.selectList(null);//baseMapper 这就是 CategoryDao

        //2.组装成父子的树形结构
        //首先需要找到所有的一级分类 一级分类最大的特点就是它们的 父分类的ID 为0 以此类推
//        List<CategoryEntity> level1Menus = entities.stream().filter((categoryEntity)->{
//            //过滤的条件就是 这集合中所有的父分类都一个一个ID 如果这个ID==0 那么说明这是一个一级分类
//            return categoryEntity.getParentCid()==0;
//        }).collect(Collectors.toList());//进行过滤 将最后的结果收集为一个 List
        //由于它只有一个 参数 则可以省略括号 并且只有一条语句 所以大括号也可以省略了
        List<CategoryEntity> level1Menus = entities.stream().filter(categoryEntity ->
                //过滤的条件就是 这集合中所有的父分类都一个一个ID 如果这个ID==0 那么说明这是一个一级分类
                categoryEntity.getParentCid() == 0
        ).map(menu->{//在收集之前还可以改变菜单里面的相关属性 使用map映射方法 将每一个菜单重新改变一下
            menu.setChildren(getChildrens(menu,entities));//将当前分类的子分类装进去
            return menu;//也就是相当于把当前菜单改了 然后再重新返回 再收集成list 然后所有的子菜单在哪里 这可以写一个递归的方法
        }).sorted((menu1,menu2)->{ //进行排序 传入前面的菜单  和后面的菜单进行对比 返回
            //getSort 这个方法就是它的排序字段 相减的出升降序的值
            return (menu1.getSort() == null?0:menu1.getSort()) - (menu2.getSort() == null?0:menu2.getSort());//防止空指针异常
        }).collect(Collectors.toList());//进行过滤 将最后的结果收集为一个 List
        //当一级分类挑出来后 为它的每一个分类分配子分类
        return level1Menus;
    }
    /**
     * 获取某一个菜单的 子菜单 递归查找
     * 第一个参数
     *  当前的菜单
     * 第二个参数
     *  你要从哪里获取它的子菜单
     * @return
     */
    private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all ){
        List<CategoryEntity> children = all.stream().filter(categoryEntity -> {//首先还是需要过滤
            return categoryEntity.getParentCid() == root.getCatId();//如果它的父ID等于当前指定的菜单的ID那么说明当前菜单就是它的子菜单
        }).map(categoryEntity -> {//可能子菜单还会有子菜单 包括这些菜单还是需要排序的
            //需要注意的是 这是一个递归找法 找的时候会重新从这个方法进来 如果有子菜单继续找
            //将菜单里面的东西重新映射一下
            categoryEntity.setChildren(getChildrens(categoryEntity,all));//为当前菜单在all里面找子菜单
            return categoryEntity;//返回当前菜单
        }).sorted((menu1,menu2) ->{//进行排序
            return (menu1.getSort() == null?0:menu1.getSort()) - (menu2.getSort() == null?0:menu2.getSort());//防止空指针异常
        }).collect(Collectors.toList());
        return children;
    }

    /**
     * 批量删除方法
     * @param asList
     */
    @Override
    public void removeMenuByIds(List<Long> asList) {
        //TODO 检查当前需要删除的菜单 是否在别的地方被调用了
        //调用原生Mapper的批量删除方法 但是这个删除在开发期间用的不多 一般都会使用逻辑删除
        /*
            逻辑删除
                使用某个字段表示 这个数据是否被删除
         */
        baseMapper.deleteBatchIds(asList);
    }

    @Override
    public Long[] findCatelogPath(Long catelogId) {
        List<Long> paths = new ArrayList<>();
        // 收集当前ID的层级关系 首先需要查出当前分类ID的 详细信息
        List<Long> parentPath = findParentPath(catelogId, paths);
        // 此时获得的数据 排序是有问题的(父/子/孙) 所以需要用到集合的排序方法
        Collections.reverse(parentPath);// 使用集合工具类 逆序转换过来
        return (Long[]) paths.toArray(new Long[parentPath.size()]);
    }

    /**
     * 级联更新
     * @param category
     */
    @Transactional
    @Override
    public void updateCascade(CategoryEntity category) {
        this.updateById(category);
        categoryBrandRelationService.updateCategory(category.getCatId(),category.getName());
    }

    private List<Long> findParentPath(Long catelogId, List<Long> paths){
        // 收集当前节点ID
        paths.add(catelogId);
        CategoryEntity byId = this.getById(catelogId);
        if (byId.getParentCid() != 0){
            findParentPath(byId.getParentCid(),paths);
        }
        return paths;
    }
}